/**
 * 
 */
package com.gr.experimental.model.impl;

import java.util.Collections;
import java.util.List;

import com.gr.experimental.model.Distribution;
import com.gr.experimental.model.Node;
import com.gr.experimental.model.RVArgument;
import com.gr.experimental.model.RVClass;
import com.gr.experimental.model.RVClassInfluence;
import com.gr.experimental.model.ResidentNode;
import com.gr.experimental.model.impl.distr.DistributionException;

/**
 * Resident node implementation.
 * @author Karol Banczyk
 */
class ResidentNodeImpl extends NodeImpl implements ResidentNode {

	private List<? extends Node> parents;
	private Distribution distribution;
	
	/**
	 * 
	 * @param rvClass
	 * @param parents
	 * @param distribution
	 * @param arguments
	 */
	public ResidentNodeImpl(RVClass rvClass, 
			Distribution distribution,
			List<? extends RVArgument> arguments,
			List<? extends Node> parents) {
		super(rvClass, arguments);
		// TODO: assert that nodes correspond to the condition random variables of the distribution
		this.parents = parents;
		this.distribution = distribution;
		
		
		
		if (parents.size() != distribution.getConditionRVClasses().size()) {
			throw new IllegalArgumentException("Parent nodes number different from distribution condition random variables number.");
		}
		int i=0;
		for (Node node: parents) {
			if (! node.getRVClass().equals(distribution.getConditionRVClasses().get(i)) ) {
				throw new IllegalArgumentException("Parent nodes inconsistent with distribution.");
			}
			i++;
		}
	}

	/**
	 * The constructor to a resident node with no parents.
	 * @param rvClass
	 * @param distribution
	 * @param arguments
	 */
	public ResidentNodeImpl(RVClass rvClass, 
			Distribution distribution,
			List<? extends RVArgument> arguments) {
		super(rvClass, arguments);


		try {
			if (rvClass.getDomain().size() != distribution.getProbabilities().length) {
				throw new IllegalArgumentException("Domain size doesn't correspond to the default probability size");
			}
			this.parents = Collections.emptyList();
			this.distribution = distribution;

		} catch (DistributionException e) {
			throw new IllegalArgumentException(e);
		}	
	}

	/**
	 * {@inheritDoc}
	 * @throws DistributionException 
	 * @see com.gr.exp.reasoner.RVClass#getProbabilities(java.util.List)
	 */
	@Override
	public double[] getDistribution(
			List<RVClassInfluence> partialWorldState) throws DistributionException {

		return distribution.getProbabilities(partialWorldState);
	}

	/**
	 * {@inheritDoc}
	 * @see com.gr.exp.reasoner.RVClass#getProbabilities()
	 */
	@Override
	public double[] getDistribution() throws DistributionException{
		return distribution.getProbabilities();
	}

	/**
	 * {@inheritDoc}
	 * @see com.gr.experimental.model.ResidentNode#getParents()
	 */
	@Override
	public List<? extends Node> getParents() {
		return parents; //distribution.getConditionRVClasses();
	}

}
